# SVG后处理工具
import re
import numpy as np
from xml.dom.minidom import Document
from svgpathtools import parse_path, Line, QuadraticBezier, CubicBezier
from xml.dom.minidom import parseString
from src.data_preprocessing.svg_constants import SVG_COMMANDS

def commands_to_svg(commands, char='', viewbox_scale=1.2):
    """
    将路径坐标序列转换为标准SVG字符串
    输入格式假设为: [(command, [coordinates]), ...]
    示例输入: [('M', [10,20]), ('L', [30,40])]
    """
    path_str = []
    for cmd, points in commands:
        if cmd == 'M':
            path_str.append(f"M {points[0]:.2f},{points[1]:.2f}")
        elif cmd == 'L':
            path_str.append(f"L {points[0]:.2f},{points[1]:.2f}")
        elif cmd == 'Q':
            path_str.append(f"Q {points[0]:.2f},{points[1]:.2f} "
                            f"{points[2]:.2f},{points[3]:.2f}")
        elif cmd == 'C':
            path_str.append(f"C {points[0]:.2f},{points[1]:.2f} "
                            f"{points[2]:.2f},{points[3]:.2f} "
                            f"{points[4]:.2f},{points[5]:.2f}")
        elif cmd == 'Z':
            path_str.append("Z")
    
    # 自动计算视图框
    path_obj = parse_path(' '.join(path_str))
    bbox = path_obj.bbox()
    viewbox = [
        bbox[0].real - 50,
        bbox[1].real - 50,
        (bbox[2] - bbox[0]).real * viewbox_scale,
        (bbox[3] - bbox[1]).real * viewbox_scale
    ]
    
    # 构建SVG文档
    doc = Document()
    svg = doc.createElement('svg')
    svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
    svg.setAttribute('viewBox', ' '.join(map(str, viewbox)))
    
    # 添加路径
    path = doc.createElement('path')
    path.setAttribute('d', ' '.join(path_str))
    path.setAttribute('fill', 'black')
    path.setAttribute('stroke', 'none')
    svg.appendChild(path)
    
    # 添加元数据
    metadata = doc.createElement('metadata')
    metadata.appendChild(doc.createTextNode(f'<char value="{char}"/>'))
    svg.appendChild(metadata)
    
    doc.appendChild(svg)
    return doc.toprettyxml()

def simplify_path(d, tolerance=2):
    """使用Ramer-Douglas-Peucker算法简化路径"""
    path = parse_path(d)
    simplified = []
    
    for seg in path:
        if isinstance(seg, (Line, QuadraticBezier, CubicBezier)):
            points = [seg.start] + ([] if isinstance(seg, Line) else [seg.control1]) + [seg.end]
            simplified.extend([(points[i].real, points[i].imag) for i in range(len(points))])
    
    if len(simplified) < 2:
        return d
    
    # RDP算法实现
    def rdp(points, epsilon):
        if len(points) < 3:
            return points
        dmax = 0
        index = 0
        end = len(points)-1
        for i in range(1, end):
            d = np.abs(np.cross(points[end]-points[0], points[i]-points[0])) / np.linalg.norm(points[end]-points[0])
            if d > dmax:
                dmax = d
                index = i
        if dmax > epsilon:
            return rdp(points[:index+1], epsilon) + rdp(points[index:], epsilon)[1:]
        else:
            return [points[0], points[-1]]
    
    points = np.array(simplified)
    simplified = rdp(points, tolerance)
    
    return ' '.join([f"M {simplified[0][0]},{simplified[0][1]}"] +
                   [f"L {x},{y}" for x,y in simplified[1:]])

def merge_svgs(svg_dict, output_path):
    """合并多个字符SVG为完整字体文件"""
    doc = Document()
    svg = doc.createElement('svg')
    svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
    svg.setAttribute('viewBox', '0 0 1024 1024')
    
    defs = doc.createElement('defs')
    style = doc.createElement('style')
    style.appendChild(doc.createTextNode('''
        .char-path { fill: black; stroke: none; }
    '''))
    defs.appendChild(style)
    svg.appendChild(defs)
    
    group = doc.createElement('g')
    group.setAttribute('transform', 'scale(0.8 0.8) translate(50,50)')
    
    for idx, (char, svg_str) in enumerate(svg_dict.items()):
        char_group = doc.createElement('g')
        char_group.setAttribute('class', f'char-{char}')
        char_group.setAttribute('transform', f'translate({(idx%10)*100}, {(idx//10)*100})')
        
        # 解析单个字符SVG
        char_doc = parseString(svg_str).documentElement
        path = char_doc.getElementsByTagName('path')[0]
        path.setAttribute('class', 'char-path')
        
        char_group.appendChild(path)
        group.appendChild(char_group)
    
    svg.appendChild(group)
    with open(output_path, 'w') as f:
        f.write(doc.toprettyxml())

def validate_svg_path(d):
    """验证并修复SVG路径语法"""
    pattern = re.compile(r'([A-Za-z])([^A-Za-z]*)')
    # 修改为使用统一的命令常量
    valid_commands = set(SVG_COMMANDS)  # 使用svg_constants.py中的定义
    
    repaired = []
    for match in pattern.finditer(d):
        cmd, args = match.groups()
        if cmd.upper() in valid_commands:
            repaired.append(cmd.upper() + ' ' + ' '.join(args.strip().split()))
    
    return ' '.join(repaired)

def commands_to_svg(commands, char='', viewbox_scale=1.2):
    """将路径坐标序列转换为标准SVG字符串"""
    path_str = []
    for cmd, points in commands:
        # 保持与svg_constants.py一致的命令处理
        if cmd == 'M':
            path_str.append(f"M {points[0]:.2f},{points[1]:.2f}")
        elif cmd == 'L':
            path_str.append(f"L {points[0]:.2f},{points[1]:.2f}")
        elif cmd == 'Q':
            path_str.append(f"Q {points[0]:.2f},{points[1]:.2f} "
                          f"{points[2]:.2f},{points[3]:.2f}")
        elif cmd == 'C':
            path_str.append(f"C {points[0]:.2f},{points[1]:.2f} "
                          f"{points[2]:.2f},{points[3]:.2f} "
                          f"{points[4]:.2f},{points[5]:.2f}")
        elif cmd == 'Z':
            path_str.append("Z")
    
    # 自动计算视图框
    path_obj = parse_path(' '.join(path_str))
    bbox = path_obj.bbox()
    viewbox = [
        bbox[0].real - 50,
        bbox[1].real - 50,
        (bbox[2] - bbox[0]).real * viewbox_scale,
        (bbox[3] - bbox[1]).real * viewbox_scale
    ]
    
    # 构建SVG文档
    doc = Document()
    svg = doc.createElement('svg')
    svg.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
    svg.setAttribute('viewBox', ' '.join(map(str, viewbox)))
    
    # 添加路径
    path = doc.createElement('path')
    path.setAttribute('d', ' '.join(path_str))
    path.setAttribute('fill', 'black')
    path.setAttribute('stroke', 'none')
    svg.appendChild(path)
    
    # 添加元数据
    metadata = doc.createElement('metadata')
    metadata.appendChild(doc.createTextNode(f'<char value="{char}"/>'))
    svg.appendChild(metadata)
    
    doc.appendChild(svg)
    return doc.toprettyxml()